﻿using System.Collections;
using UnityEngine;

/// <summary>
/// 使用鼠标（或触控）控制摄像机的观察方位
/// </summary>
public class CameraManager : MonoBehaviour
{
    public float size = 1.0f;

    float radius = 1.0f;

    Camera cam;

    float leftRight = 0;
    float upDown = 0;

    float lr_speed = 0;
    float ud_speed = 0;

    private void Awake()
    {
        cam = GetComponent<Camera>();
    }

    // Start is called before the first frame update
    void Start()
    {
        UpdateCamera();
    }

    // Update is called once per frame
    void Update()
    {
        DealInput();

        UpdateCamera();
    }

    float touchDist = 0;
    Vector3 lastPos;
    Vector3 startPos;
    bool singleFinger = false;

    float lastClickTime;
    void DealInput()
    {
        var sc = Input.GetAxis("Mouse ScrollWheel");
        if (sc != 0)
            size += sc * 0.2f;

        if (Input.touchCount == 2)
        {
            singleFinger = false;
            var touch0 = Input.GetTouch(0);
            var touch1 = Input.GetTouch(1);
            var dist = Vector2.Distance(touch0.position, touch1.position);
            if (touch0.phase == TouchPhase.Began || touch1.phase == TouchPhase.Began)
            {
            }
            else
            {
                var delta = dist - touchDist;
                size += (2.0f * delta) / (Screen.width + Screen.height);
            }
            touchDist = dist;
        }
        else if (Input.GetMouseButtonDown(0))
        {
            singleFinger = true;
            lr_speed = 0;
            ud_speed = 0;
            startPos =
                lastPos = Input.mousePosition;

        }
        else if (Input.GetMouseButton(0))
        {
            if (!singleFinger) return;

            var delta = Input.mousePosition - lastPos;
            delta /= (Screen.width + Screen.height);

            leftRight += delta.x * 300 / size / size;
            upDown += delta.y * 300 / size / size;
            startPos = lastPos;
            lastPos = Input.mousePosition;
        }
        else if (Input.GetMouseButtonUp(0))
        {
            if (!singleFinger) return;

            if (Time.unscaledTime - lastClickTime < 0.3f)
            {
                if (cor == null)
                {
                    cor = StartCoroutine(SizeChange());
                }
                lastClickTime = 0;
            }
            else
            {

                lastClickTime = Time.unscaledTime;
            }

            var delta = Input.mousePosition - lastPos;
            delta /= (Screen.width + Screen.height);

            if (Vector3.Distance(Input.mousePosition, startPos) / (Screen.width + Screen.height) > 0.01f)
            {
                lr_speed = delta.x * 14400 / size;
                ud_speed = delta.y * 14400 / size;
                lr_speed = Mathf.Clamp(lr_speed, -2400, 2400);
                ud_speed = Mathf.Clamp(ud_speed, -2400, 2400);
            }
            singleFinger = false;
        }

    }

    Coroutine cor;

    IEnumerator SizeChange()
    {
        var currentS = size;
        var targetS = currentS == 1 ? 1.6f : 1;

        var lr = leftRight;
        //TODO: 摄像机聚焦点击位置
        var targetLR = currentS == 1 ? leftRight 
            : leftRight;
        var ud = upDown;
        var targetud = currentS == 1 ? upDown
            : 0;

        const int count = 12;
        const float delta = 1.0f / count;
        for (int i = 0; i < count; i++)
        {
            size = Mathf.Lerp(currentS, targetS, i * delta);
            leftRight = Mathf.Lerp(lr, targetLR, i * delta);
            upDown = Mathf.Lerp(ud, targetud, i * delta);
            yield return null;
        }
        size = targetS;

        cor = null;
    }

    const float kDefaultDist = 4;
    const float kMaxSize = 2.4f;
    void UpdateCamera()
    {
        size = Mathf.Clamp(size, 0.5f, kMaxSize);

        if (Screen.width > Screen.height)
        {
            radius = kDefaultDist / size;
        }
        else
        {
            if (size < 1)
                radius = kDefaultDist / Screen.width * Screen.height / size;
            else
                radius = Mathf.Lerp(kDefaultDist / Screen.width * Screen.height / size, kDefaultDist / size, (size - 1) / (kMaxSize - 1));
        }

        if (Mathf.Abs(ud_speed) > 0.1f)
        {
            upDown += ud_speed * Time.deltaTime;
            ud_speed *= 0.96f;
        }
        if (Mathf.Abs(lr_speed) > 0.1f)
        {

            leftRight += lr_speed * Time.deltaTime;
            lr_speed *= 0.96f;
        }


        cam.transform.localEulerAngles = new Vector3(-upDown, leftRight, 0);
        cam.transform.position = -cam.transform.forward * radius;
    }
}
